from scipy.optimize import minimize
import numpy as np

def count_target(r, a, b, c, target):
    now = {
        'calorie': 0,
        'protein': 0,
        'fat': 0,
        'carbohydrate': 0
    }
    for item_a in a:
        now['calorie'] += item_a['Calorie']
        now['protein'] += item_a['Protein']
        now['fat'] += item_a['Fat']
        now['carbohydrate'] += item_a['Carbohydrate']
    for i_b, item_b in enumerate(b):
        now['calorie'] += item_b['Calorie'] * r[i_b]
        now['protein'] += item_b['Protein'] * r[i_b]
        now['fat'] += item_b['Fat'] * r[i_b]
        now['carbohydrate'] += item_b['Carbohydrate'] * r[i_b]
    # calorie3 = 0
    for i_c, item_c in enumerate(c):
        idx = i_c + len(b)
        # calorie3 += item_c['Calorie'] * r[i_c + len(b) - 1]
        now['calorie'] += item_c['Calorie'] * r[idx]
        now['protein'] += item_c['Protein'] * r[idx]
        now['fat'] += item_c['Fat'] * r[idx]
        now['carbohydrate'] += item_c['Carbohydrate'] * r[idx]

    return (now['protein'] / target['protein'] - 1) ** 2 + (now['fat'] / target['fat'] - 1) ** 2 + (now['carbohydrate'] / target['carbohydrate'] - 1) ** 2

def con_fun(r, a, b, c, target):
    now = {
        'calorie': 0,
        'protein': 0,
        'fat': 0,
        'carbohydrate': 0
    }
    for item_a in a:
        now['calorie'] += item_a['Calorie']
        now['protein'] += item_a['Protein']
        now['fat'] += item_a['Fat']
        now['carbohydrate'] += item_a['Carbohydrate']
    for i_b, item_b in enumerate(b):
        now['calorie'] += item_b['Calorie'] * r[i_b]
        now['protein'] += item_b['Protein'] * r[i_b]
        now['fat'] += item_b['Fat'] * r[i_b]
        now['carbohydrate'] += item_b['Carbohydrate'] * r[i_b]
    # calorie3 = 0
    for i_c, item_c in enumerate(c):
        idx = i_c + len(b)
        # calorie3 += item_c['Calorie'] * r[i_c + len(b) - 1]
        now['calorie'] += item_c['Calorie'] * r[idx]
        now['protein'] += item_c['Protein'] * r[idx]
        now['fat'] += item_c['Fat'] * r[idx]
        now['carbohydrate'] += item_c['Carbohydrate'] * r[idx]

    ratio = {
        'calorie': now['calorie'] / target['calorie'],
        'protein': now['protein'] / target['protein'],
        'fat': now['fat'] / target['fat'],
        'carbohydrate': now['carbohydrate'] / target['carbohydrate']
    }

    return ratio

def lp_problem(a, b, c, target):
    print(target)
    n = len(b) + len(c)

    # 变量范围
    bounds = [(1, 5) for _ in range(n)]

    # 设置初始猜测值
    x0 = np.ones(n)

    # 构造约束条件
    cons = [
        {'type': 'ineq', 'fun': lambda r: con_fun(r, a, b, c, target)['calorie'] - 0.8},
        {'type': 'ineq', 'fun': lambda r: 1.05 - con_fun(r, a, b, c, target)['calorie']},
        {'type': 'ineq', 'fun': lambda r: con_fun(r, a, b, c, target)['protein'] - 0.95},
        {'type': 'ineq', 'fun': lambda r: con_fun(r, a, b, c, target)['fat'] - 0.95},
        {'type': 'ineq', 'fun': lambda r: con_fun(r, a, b, c, target)['carbohydrate'] - 0.95},
        {'type': 'ineq', 'fun': lambda r: 1.8 - con_fun(r, a, b, c, target)['protein']},
        {'type': 'ineq', 'fun': lambda r: 1.4 - con_fun(r, a, b, c, target)['fat']},
        {'type': 'ineq', 'fun': lambda r: 1.4 - con_fun(r, a, b, c, target)['carbohydrate']}
    ]

    result = minimize(
        fun=count_target,
        x0=x0,
        args=(a, b, c, target),
        method='SLSQP',
        bounds=bounds,
        constraints=cons
    )

    if result.success:
        print("最优解:", [round(float(val), 2) for val in result.x])
        return [round(float(val), 2) for val in result.x]
    # else:
    #     print("未找到可行解:", result.message)


if __name__ == '__main__':
    a = [{'name': '红枣煲鸡蛋', 'Calorie': 252.0, 'Protein': 13.799999999999999, 'Fat': 8.399999999999999, 'Carbohydrate': 10.8, 'Per_Edible': 150.0}, {'name': '含铁婴儿米粉', 'Calorie': 192.0, 'Protein': 3.6, 'Fat': 0.8, 'Carbohydrate': 43.0, 'Per_Edible': 150.0}]
    b = [{'name': '芹菜炒辣椒', 'Calorie': 28.0, 'Protein': 0.9, 'Fat': 0.4, 'Carbohydrate': 6.7, 'Per_Edible': 140.0}, {'name': '樱桃汁', 'Calorie': 46.0, 'Protein': 1.1, 'Fat': 0.2, 'Carbohydrate': 10.2, 'Per_Edible': 100.0}, {'name': '家常胡萝卜烧香菇', 'Calorie': 90.0, 'Protein': 2.5, 'Fat': 3.4, 'Carbohydrate': 14.8, 'Per_Edible': 160.0}, {'name': '八块鸡', 'Calorie': 164.0, 'Protein': 9.2, 'Fat': 12.6, 'Carbohydrate': 1.1, 'Per_Edible': 86.0}]
    c = [{'name': '芝麻海蜇', 'Calorie': 105.0, 'Protein': 7.5, 'Fat': 4.5, 'Carbohydrate': 8.9, 'Per_Edible': 163.0}, {'name': '山楂陈皮茶', 'Calorie': 140.0, 'Protein': 1.4, 'Fat': 0.4, 'Carbohydrate': 17.4, 'Per_Edible': 70.0}]
    target = {'calorie': 2197.7, 'protein': 45.5, 'fat': 42.7, 'carbohydrate': 230.8}
    lp_problem(a, b, c, target)

